/*
 * Copyright 2008-2023, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Michael Lotz <mmlr@mlotz.ch>
 */
#ifndef _USB_DISK_H_
#define _USB_DISK_H_


#include <util/Vector.h>
#include <util/DoublyLinkedList.h>

#include <lock.h>
#include <USB3.h>
#include <device_manager.h>
#include <usb/USB_massbulk.h>


#define REQUEST_MASS_STORAGE_RESET	0xff
#define REQUEST_GET_MAX_LUN			0xfe
#define MAX_LOGICAL_UNIT_NUMBER		15
#define ATAPI_COMMAND_LENGTH		12

#define SYNC_SUPPORT_RELOAD			5

struct IOScheduler;
struct DMAResource;
typedef struct device_lun_s device_lun;

// holds common information about an attached device (pointed to by luns)
typedef struct disk_device_s {
	disk_device_s();
	~disk_device_s();

	int32		number;
	device_node	*node;

	usb_device	device;
	bool		removed;
	uint32		open_count;
	recursive_lock io_lock;
	mutex		lock;

	// IO operations
	Vector<DMAResource*>	dma_resources;

	// device state
	usb_pipe	bulk_in;
	usb_pipe	bulk_out;
	usb_pipe	interrupt;
	uint8		interface;
	uint32		current_tag;
	uint8		sync_support;
	bool		tur_supported;
	bool		is_atapi;
	bool		is_ufi;

	// used to store callback information
	sem_id		notify;
	status_t	status;
	size_t		actual_length;

	// used to store interrupt result
	unsigned char interruptBuffer[2];
	sem_id interruptLock;

	// logical units of this device
	uint8		lun_count;
	device_lun **luns;
} disk_device;


// represents a logical unit on the pointed to device - this gets published
struct device_lun_s {
	disk_device *device;
	char		name[32];
	uint8		logical_unit_number;
	bool		should_sync;

	// device information through read capacity/inquiry
	bool		media_present;
	bool		media_changed;
	uint64		block_count;
	uint32		block_size;
	uint32		physical_block_size;
	uint8		device_type;
	bool		removable;
	bool		write_protected;

	char		vendor_name[8];
	char		product_name[16];
	char		product_revision[4];
};


typedef struct interrupt_status_wrapper_s {
	uint8		status;
	uint8		misc;
} _PACKED interrupt_status_wrapper;


#endif // _USB_DISK_H_
